package person.twj.jwt.core.security.handler;

import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Lists;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.GenericFilterBean;
import person.twj.jwt.core.security.constant.TokenConstants;
import person.twj.jwt.core.security.util.UserToken;
import person.twj.jwt.core.security.util.TokenUtil;
import person.twj.jwt.domain.vo.RsVo;

import java.io.IOException;
import java.util.*;

/**
 * token拦截器，主要功能：
 * 1. 验证token是否有效。
 */
@Slf4j
public class TokenVerifyFilter extends GenericFilterBean {





    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        String token = getTokenFromRequestHeader(request);

        log.debug("header {}",toHeaderString(request));
        // token验证失败，

        if(StringUtils.isNotBlank(token)){
            // 解析token
            UserToken userToken = null;
            try {
                userToken = TokenUtil.parseTokenInfo(token);

            }catch (BadCredentialsException e){
                RsVo.failed(1,"令牌不正确").writeTo(response);
                return;
            }catch (CredentialsExpiredException cee){
                RsVo.failed(3,"令牌已过期").writeTo(response);
                return;
            }catch (Exception e){
                log.debug("未知错误 ",e);
                RsVo.failed(-1,"未知错误").writeTo(response);
                return;
            }

            Collection<GrantedAuthority> authorities = new ArrayList<>();
            // 把userToken存起来，给后续使用
            request.setAttribute(UserToken.class.getName(),userToken);
            //更新security登录用户对象
            UsernamePasswordAuthenticationToken authenticationToken =
                    new UsernamePasswordAuthenticationToken(
                            userToken.getUserId(),
                            null,
                            authorities
                    );
            // 如果验证成功，则把手动直接认证，并交给下个判断是否已登录。
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);


        }
        // 交给下个 Filter
        chain.doFilter(request, response);

    }

    private String toHeaderString(HttpServletRequest request) {
        Iterator<String> headerNames = request.getHeaderNames().asIterator();
        Map<String, Object> map = new HashMap<>();
        for (String name : Lists.newArrayList(headerNames)) {
            map.put(name, request.getHeader(name));
        }
        return JSON.toJSONString(map);
    }

    /**
     * 从header中获取token，这里采用原始的格式
     * <br><br>
     * Authorization: Bearer <token>
     * <br><br>
     * @param request
     * @return
     */
    public static String getTokenFromRequestHeader(HttpServletRequest request) {
        String authorizationStr = request.getHeader(TokenConstants.AUTHENTICATION);
        String token = "";
        if(StringUtils.isNotBlank(authorizationStr)&&authorizationStr.startsWith(TokenConstants.PREFIX)){
            token = authorizationStr.substring(TokenConstants.PREFIX.length());
        }

        return token;
    }




    //  验证token有效性

}
